﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric;

namespace HYRElectric.Calculate
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CmdIllCalculate : YJKCommandManual
	{
		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			this.ShowMainDlg();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void ShowMainDlg()
		{
			try
			{
				if (this.m_dlgIllCal == null)
				{
					this.m_dlgIllCal = new DlgIllCalMain(this.m_uiApp);
				}
				DialogResult dialogResult = this.m_dlgIllCal.ShowDialog();
				if (dialogResult == DialogResult.OK)
				{
					if (this.m_dlgIllCal.m_nDlgRstType == 0)
					{
						Space space = this.SelectRoom();
						if (space != null)
						{
							this.AddSpaceToDlg(space);
						}
					}
					else if (this.m_dlgIllCal.m_nDlgRstType != 1)
					{
						if (this.m_dlgIllCal.m_nDlgRstType == 2)
						{
							List<Space> list = this.SelectSpaces();
							if (list == null)
							{
								goto IL_F6;
							}
							using (List<Space>.Enumerator enumerator = list.GetEnumerator())
							{
								while (enumerator.MoveNext())
								{
									Space space2 = enumerator.Current;
									this.AddSpaceToDlg(space2);
								}
								goto IL_F6;
							}
						}
						if (this.m_dlgIllCal.m_nDlgRstType == 3)
						{
							using (List<Space>.Enumerator enumerator = this.SelectAllSpaces().GetEnumerator())
							{
								while (enumerator.MoveNext())
								{
									Space space3 = enumerator.Current;
									this.AddSpaceToDlg(space3);
								}
								goto IL_F6;
							}
							goto IL_F4;
						}
					}
					IL_F6:
					this.ShowMainDlg();
				}
				IL_F4:;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		private Space SelectRoom()
		{
			Space result = null;
			try
			{
                Assist.SpaceFilter spaceFilter = new Assist.SpaceFilter();
				Reference reference = this.m_uiDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, spaceFilter, "请选择一个空间");
				if (reference != null)
				{
					result = (this.m_doc.GetElement(reference) as Space);
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				return null;
			}
			return result;
		}

		private List<Space> SelectSpaces()
		{
			List<Space> list = new List<Space>();
			try
			{
                Assist.SpaceFilter spaceFilter = new Assist.SpaceFilter();
				foreach (Reference reference in this.m_uiDoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, spaceFilter, "请选择空间："))
				{
					Space item = this.m_doc.GetElement(reference) as Space;
					list.Add(item);
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				return null;
			}
			return list;
		}

		private List<Space> SelectAllSpaces()
		{
			List<Space> list = new List<Space>();
			try
			{
				ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaces);
				foreach (Element element in new FilteredElementCollector(this.m_doc).OfClass(typeof(SpatialElement)).WherePasses(elementCategoryFilter).ToElements())
				{
					Space space = element as Space;
					if (space != null && space.IsHasBoundary())
					{
						list.Add(space);
					}
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				return null;
			}
			return list;
		}

		private void AddSpaceToDlg(Space space)
		{
			bool flag = false;
			for (int i = 0; i < this.m_dlgIllCal.m_illCalData.arDGVData.Count; i++)
			{
				if (this.m_dlgIllCal.m_illCalData.arDGVData.ElementAt(i).room != null && space.Id.IntegerValue == this.m_dlgIllCal.m_illCalData.arDGVData.ElementAt(i).room.Id.IntegerValue)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				this.m_dlgIllCal.InsertNewRow();
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dGZMGD = Math.Round(AssistFunc.feetToMM(space.get_Parameter(BuiltInParameter.RBS_ELEC_ROOM_LIGHTING_CALC_WORKPLANE).AsDouble()) / 1000.0, 2);
				try
				{
					this.m_dlgIllCal.m_illCalData.activeDGVRowData.dYQGLMD = (double)space.GetParameter("照明标准").AsInteger();
				}
				catch (Exception)
				{
				}
				try
				{
					this.m_dlgIllCal.m_illCalData.activeDGVRowData.dPJZD = space.GetParameter("照度").AsDouble();
				}
				catch (Exception)
				{
				}
				FSXSData fsxsdata = new FSXSData();
				fsxsdata.dValue = space.get_Parameter(BuiltInParameter.RBS_ELEC_ROOM_REFLECTIVITY_WALLS).AsDouble() * 100.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dSBFSXS = fsxsdata;
				FSXSData fsxsdata2 = new FSXSData();
				fsxsdata2.dValue = space.get_Parameter(BuiltInParameter.RBS_ELEC_ROOM_REFLECTIVITY_WALLS).AsDouble() * 100.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dXBFSXS = fsxsdata2;
				FSXSData fsxsdata3 = new FSXSData();
				fsxsdata3.dValue = space.get_Parameter(BuiltInParameter.RBS_ELEC_ROOM_REFLECTIVITY_CEILING).AsDouble() * 100.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dDPFSXS = fsxsdata3;
				FSXSData fsxsdata4 = new FSXSData();
				fsxsdata4.dValue = space.get_Parameter(BuiltInParameter.RBS_ELEC_ROOM_REFLECTIVITY_FLOOR).AsDouble() * 100.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dDMFSXS = fsxsdata4;
				double num = space.get_Parameter(BuiltInParameter.ROOM_UPPER_OFFSET).AsDouble();
				double num2 = space.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET).AsDouble();
				double num3 = AssistFunc.feetToMM(num - num2) / 1000.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dFJGD = num3;
				if (this.m_dlgIllCal.m_illCalData.activeDGVRowData.dAZGD > num3)
				{
					this.m_dlgIllCal.m_illCalData.activeDGVRowData.dAZGD = num3;
				}
				string value = AssistFunc.feet2ToM2(space.Area).ToString("0.00");
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dFJMJ = Convert.ToDouble(value);
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.nFJBH = Convert.ToInt32(space.get_Parameter(BuiltInParameter.ROOM_NUMBER).AsString());
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.sFJMC = space.get_Parameter(BuiltInParameter.ROOM_NAME).AsString();
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dPerimeter = AssistFunc.feetToMM(space.Perimeter) / 1000.0;
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.dWallPerimeter = AssistFunc.feetToMM(this.GetWallPerimeter(space)) / 1000.0;
				this.GetRoomOpeningData(space, ref this.m_dlgIllCal.m_illCalData.activeDGVRowData);
				this.m_dlgIllCal.m_illCalData.activeDGVRowData.room = space;
				return;
			}
			MessageBox.Show("空间" + space.Name + "已存在，不能重复添加！");
		}

		private double GetWallPerimeter(Space space)
		{
			double num = 0.0;
			List<ElementId> list = new List<ElementId>();
			if (!space.IsHasBoundary())
			{
				return num;
			}
			foreach (IList<BoundarySegment> list2 in this.GetRoomBoundarys(space))
			{
				foreach (BoundarySegment segment in list2)
				{
					Wall wall = segment.GetElement(this.m_doc) as Wall;
					if (wall != null && !list.Contains(wall.Id))
					{
						list.Add(wall.Id);
						num += segment.GetCurve().Length;
					}
				}
			}
			return num;
		}

		private void GetRoomOpeningData(Space room, ref DGVRowData rowData)
		{
			Level level = room.Level;
			double num = 0.0;
			List<ElementId> list = new List<ElementId>();
			if (!room.IsHasBoundary())
			{
				return;
			}
			foreach (IList<BoundarySegment> list2 in this.GetRoomBoundarys(room))
			{
				foreach (BoundarySegment segment in list2)
				{
					Wall wall = segment.GetElement(this.m_doc) as Wall;
					if (wall != null && !list.Contains(wall.Id))
					{
						list.Add(wall.Id);
						if (wall != null)
						{
                            IList<FamilyInstance> wallAssoDoorWins = WallAssistFunc.GetWallAssoDoorWins(this.m_doc, wall, (BuiltInCategory)(-2000014), level);
							if (wallAssoDoorWins != null)
							{
								foreach (FamilyInstance familyInstance in wallAssoDoorWins)
								{
									LocationPoint locationPoint = familyInstance.Location as LocationPoint;
									XYZ offsetDoorWinPosition = this.GetOffsetDoorWinPosition(wall, locationPoint.Point, 1);
									XYZ offsetDoorWinPosition2 = this.GetOffsetDoorWinPosition(wall, locationPoint.Point, -1);
									if (room.IsPointInSpace(offsetDoorWinPosition) || room.IsPointInSpace(offsetDoorWinPosition2))
									{
										FamilySymbol symbol = familyInstance.Symbol;
										if (symbol != null)
										{
											double num2 = AssistFunc.feetToMM(symbol.get_Parameter(BuiltInParameter.FAMILY_HEIGHT_PARAM).AsDouble()) / 1000.0;
											double num3 = AssistFunc.feetToMM(symbol.get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble()) / 1000.0;
											double num4 = num2 * num3;
											num += num4;
										}
									}
								}
							}
						}
					}
				}
			}
			rowData.dCMJ = Math.Round(num, 2);
		}

		private IList<IList<BoundarySegment>> GetRoomBoundarys(Space room)
		{
			if (room == null)
			{
				return null;
			}
			return room.GetBoundarySegments(new SpatialElementBoundaryOptions());
		}

		private XYZ GetOffsetDoorWinPosition(Wall wall, XYZ OriPos, int dir)
		{
			XYZ result = new XYZ();
			if (WallAssistFunc.GetWallCurveType(wall) == WallCurveType.eLineWall)
			{
				XYZ startPt = WallAssistFunc.GetStartPt(wall);
				XYZ xyz = (WallAssistFunc.GetEndPt(wall) - startPt).Normalize();
				xyz = RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, Math.PI*.5, XYZ.Zero).OfVector(xyz);
				result = OriPos + xyz * (double)dir * AssistFunc.mmToFeet(WallAssistFunc.GetWallThick(this.m_doc, wall) * 1.5);
			}
			else if (WallAssistFunc.GetWallCurveType(wall) == WallCurveType.eArcWall)
			{
				Arc arc = (wall.Location as LocationCurve).Curve as Arc;
				if (arc == null)
				{
					return null;
				}
				XYZ center = arc.Center;
				XYZ xyz2 = (OriPos - center).Normalize();
				result = OriPos + xyz2 * (double)dir * AssistFunc.mmToFeet(WallAssistFunc.GetWallThick(this.m_doc, wall) * 1.5);
			}
			return result;
		}

		private DlgIllCalMain m_dlgIllCal;
	}
}
